#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "ci112x_uart.h"
#include "sdk_default_config.h"

extern char heap_start, heap_end, ASR_USED_SIZE;
static int heapBytsRemaining = (int)&ASR_USED_SIZE;


int _isatty(int desc)
{
    if (desc == STDOUT_FILENO || desc == STDERR_FILENO)
    {
        return 1;
    }
    return 0;
}

static inline int _stub(int err)
{
    return -1;
}

ssize_t _read(int fd, void* ptr, size_t len)
{
    return _stub(EBADF);
}

ssize_t _write(int fd, const void* ptr, size_t len)
{
    const uint8_t * current = (const char*)ptr;
    if (isatty(fd))
    {
#ifdef STDOUT_INTERFACE
#if (STDOUT_INTERFACE == HAL_UART0_BASE) || (STDOUT_INTERFACE == HAL_UART0_BASE) || (STDOUT_INTERFACE == HAL_UART0_BASE)
        for (size_t jj = 0;jj < len; jj++)
        {
            if (current[jj] == '\n')
            {
                UartPollingSenddata((UART_TypeDef*)STDOUT_INTERFACE, '\r');
            }
            UartPollingSenddata((UART_TypeDef*)STDOUT_INTERFACE, current[jj]);
        }
#endif
#endif  
        return len;
    }
    return _stub(EBADF);
}

int _fstat(int fd, struct stat * st)
{
    if (isatty(fd))
    {
        st->st_mode = S_IFCHR;
        return 0;
    }
    return _stub(EBADF);
}

off_t _lseek(int fd, off_t offset, int whence)
{
    if (isatty(fd))
    {
        return 0;
    }
    return _stub(EBADF);
}

int _close(int fd)
{
    return _stub(EBADF);
}


char *_sbrk(int incr)
{
    static char *currentHeapEnd = &heap_start;

    #if USE_FREERTOS_SBRK
    vTaskSuspendAll();
    #endif

    char *previousHeapEnd = currentHeapEnd;
    if (currentHeapEnd + incr >= &heap_end)
    {
        _impure_ptr->_errno = ENOMEM;
        #if USE_FREERTOS_SBRK
        xTaskResumeAll();
        #endif
        return (char*)-1;
    }
    currentHeapEnd += incr;
    heapBytsRemaining -= incr;

    #if USE_FREERTOS_SBRK
    xTaskResumeAll();
    #endif
    return (char*)previousHeapEnd;
}

